#ifndef _SIMPLE_LIST_H_
#define _SIMPLE_LIST_H_

#ifdef __cplusplus
extern "C" {
#endif

#ifndef likely
#define likely(x)   __builtin_expect((x),1)
#endif
#ifndef unlikely
#define unlikely(x) __builtin_expect((x),0)
#endif

#define RUN_DEBUG_MODE
#ifdef RUN_DEBUG_MODE
#ifndef BUG_ON
#define str(x)      #x
#define xstr(x)     str(x)
#define BUG_ON(expr) {      \
        if ((expr)) { \
            fprintf(stderr, "BUG ON at %s:%d(%s)\r\n", __FILE__,__LINE__, __func__);    \
            fprintf(stderr, "Error code : %s\r\n", xstr(expr));                         \
            exit(1);                    \
        }   \
    }
#endif
#else
#define BUG_ON(expr)
#endif


#define LIST_F_ALLOCATED 0x0001     /* The list_t is allocated, will be free on destroy*/
#define LIST_F_SORTED    0x0010     /* Sort*/
#define LIST_F_UNIQUE    0x0100     /* Don't allow duplicates*/
#define LIST_F_NOTGROWS  0x1000     /* Don't allow grow*/

typedef void (*elem_free_func)(void *);
typedef int  (*elem_cmp_func) (void *s, void *d);

typedef struct _list {
	void **elems;
	int cnt;
	int size;
    unsigned int   flags;
    elem_cmp_func  elem_cmp;
	elem_free_func cb_free;
} list_t, *list_pt;



static inline void list_clear (list_t *l)
{
    l->cnt = 0;
}

static inline int list_size (list_t *l)
{
    return l->size;
}

static inline int list_cnt (list_t *l)
{
    return l->cnt;
}

static inline int list_empty (list_t *l)
{
    return l->cnt == 0;
}


#define LIST_FOREACH(l, index, elem) \
		for (index = 0; (elem = list_elem(l, index)); index++)

list_t*   list_new (int size, elem_free_func cb_free);
int       list_init(list_t *l, int size, elem_free_func cb_free);
int       list_grow (list_t* l, int size);
int       list_sort (list_t *l, int (*cmp)(const void *_a, const void *_b));
void*     list_elem (list_t *l, int index);
void*     list_find (list_t *l, const void *elem, int (*cmp)(const void *_a, const void *_b));
void      list_free_cb (list_t *l, void *ptr);
int       list_add_noduplicate (list_t *l, void *elem, int (*cmp)(const void *_a, const void *_b));
int       list_add (list_t *l, void *elem);
void*     list_remove_index(list_t *l, int idx);
void*     list_remove (list_t *l, void *elem);
void* list_remove_cmp (list_t *l, void *elem, int (*cmp)(const void *_a, const void *_b));
int       list_multi_remove_cmp (list_t *l, void *elem, int (*cmp)(const void *_a, const void *_b));
inline    void list_clear (list_t *l);
inline    int list_cnt (list_t *l);
inline    int list_empty (list_t *l);
void*     list_onlycopy_ptr (void *s, void *mt);
int       list_copy_to (list_t *dst, list_t *src, void* (*copy)(void* _d, void *_s), void* match);
void      list_free (list_t *l);
list_t*   list_copy (list_t *src, void* (*copy)(void* _d, void *_s), void* match);
void list_dump (const char *what, list_t *l);





#ifdef __cplusplus
}
#endif


#endif
